package com.dreamycode.paths;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;

/**
 * Represents the shared attributes of File/Folder and aids in working
 * with these two interfaces.
 *
 * @see File
 * @see Folder
 * @see Paths
 *
 * @author Eli Doran <eli@elidoran.com>
 *
 * @since 1.0
 */
public interface Path
{

    /**
     * Returns a java.io.File representation of this path.
     *
     * @return The java.io.File.
     *
     * @since 1.0
     */
    java.io.File asJavaFile();

    /**
     * Returns the name of the file or folder.
     *
     * @return The name..
     *
     * @since 1.0
     */
    CharSequence getName();

    /**
     * Returns the system path either relative or absolute.
     *
     * @return The path.
     *
     * @since 1.0
     */
    CharSequence getPath();

    /**
     * Returns the absolute system path.
     *
     * @return The absolute path.
     *
     * @since 1.0
     */
    CharSequence getFullPath();

    /**
     * Returns the parent folder of this path's target. If the path leads
     * to a file then it's the file's containing folder. If the path leads
     * to a folder then it is the folder's containing folder.
     *
     * @return The Folder.
     *
     * @since 1.0
     */
    Folder getFolder();

    /**
     * Returns true only if the target of this path exists.
     *
     * @return true if it exists as a file or folder.
     *
     * @see #isRealFile
     * @see #isRealFolder
     *
     * @since 1.0
     */
    boolean isReal();

    /**
     * Provides a combined check that the path points to a File and
     * that the file exists.
     *
     * <p>This is helpful when used with {@link Paths#asPath} to test the results
     * and convert to the specific type. Using {@link Paths#asFile} and
     * {@link Paths#asFolder} both may return null and so require a null
     * check as well as a type test. Using the below method may be more
     * readable.
     *<pre>
     * Example:
     *
     *   final Path path = Paths.asPath("some/path");
     *
     *   if (path.isRealFile())
     *   {
     *       final File file = path.asFile();
     *   }
     *
     *   else if (path.isRealFolder())
     *   {
     *       final Folder folder = path.asFolder();
     *   }
     * </pre>
     *
     * @return true if it is both a file and exists.
     *
     * @since 1.0
     */
    boolean isRealFile();

    /**
     * Provides a combined check that the path points to a Folder and
     * that the folder exists.
     *
     * This is helpful when used with {@link Paths#asPath} to test the results
     * and convert to the specific type. Using {@link Paths#asFile} and
     * {@link Paths#asFolder} both may return null and so require a null
     * check as well as a type test. Using the below method may be more
     * readable.
     *<pre>
     * Example:
     *
     *   final Path path = Paths.asPath("some/path");
     *
     *   if (path.isRealFile())
     *   {
     *       final File file = path.asFile();
     *   }
     *
     *   else if (path.isRealFolder())
     *   {
     *       final Folder folder = path.asFolder();
     *   }
     * </pre>
     *
     * @return true if it is both a folder and exists.
     *
     * @since 1.0
     */
    boolean isRealFolder();

    /**
     * Returns true if the path leads to a file.
     *
     * @return true if it is a file.
     *
     * @since 1.0
     */
    boolean isFile();

    /**
     * Returns true if the path leads to a folder.
     *
     * @return true if it is a folder.
     *
     * @since 1.0
     */
    boolean isFolder();

    /**
     * Returns true if it is hidden.
     *
     * @return true if it is hidden.
     *
     * @since 1.0
     */
    boolean isHidden();

    /**
     * Returns true if it is an absolute name.
     *
     * @return true if it is an absolute path.
     *
     * @since 1.0
     */
    boolean isFull();

    /**
     * Returns a File if and only if this path leads to a File. If the path
     * leads to a Folder then null is returned. If the file does not exist
     * it still returns a File.
     *
     * <p> perhaps it would be better if this threw an exception if it isn't a file.
     *
     * @return The File or null if it isn't a file.
     *
     * @since 1.0
     */
    File asFile();

    /**
     * Returns a Folder if and only if this path leads to a Folder. If the path
     * leads to a File then null is returned. If the Folder does not exist
     * it still returns a Folder.
     *
     * <p> perhaps it would be better if this threw an exception if it isn't a file.
     *
     * @return The Folder or null if it isn't a folder.
     *
     * @since 1.0
     */
    Folder asFolder();

    /**
     * Returns a URL for the target of this path.
     *
     * @return The URL.
     *
     * @throws MalformedURLException
     *
     * @since 1.0
     */
    URL asUrl();

    /**
     * Returns a URI for the target of this path.
     *
     * @return The URI.
     *
     * @since 1.0
     */
    URI asUri();


    /**
     * Returns the last modified date as a long.
     *
     * @return The last modified date.
     *
     * @since 1.0
     */
    long getModified();

    /**
     * Sets the last modified times.
     *
     * @return true if it succeeded, false otherwise.
     *
     * @since 1.0
     */
    boolean setModified(long time);

    /**
     * Renames the target's name only leaving it in the same folder.
     *
     * @param name The new name for the file or folder.
     *
     * @return true if it succeeded, false otherwise.
     *
     * @since 1.0
     */
    boolean rename(CharSequence name);

    /**
     * Renames the target to the new path which could put it somewhere
     * completely different.
     *
     * @param path The new path for the file or folder.
     *
     * @return true if it succeeded, false otherwise.
     *
     * @since 1.0
     */
    boolean moveTo(CharSequence path);

    /**
     * Renames the target to the new path which could put it somewhere
     * completely different.
     *
     * @param file The new file it should be.
     *
     * @return true if it succeeded, false otherwise.
     *
     * @since 1.0
     */
    boolean renameTo(File file);

    /**
     * Renames the target to the new path which could put it somewhere
     * completely different.
     *
     * @param file The new file it should be.
     *
     * @return true if it succeeded, false otherwise.
     *
     * @since 1.0
     */
    boolean renameTo(java.io.File file);

    /**
     * Deletes the target of this path ONLY if the target exists; if
     * path.isReal().
     *
     * @return true if it succeeded, false otherwise.
     *
     * @since 1.0
     */
    boolean delete();

}

/*
 * Copyright 2010 Eli Doran
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
